#include "UnitTest++.h"
#include "ZipReader.h"
#include "FileUtils.h"
#include "CentralDirectory.h"
#include "ZipBuilder.h"
#include <time.h>
#include <utime.h>
#include <sstream>
#include <vector>

void setLastModificationTime(const char* path)
{
    struct utimbuf utimeBuffer;
    struct tm modificationTime;
    memset(&utimeBuffer, 0, sizeof (utimbuf));

    modificationTime.tm_year = 2012 - 1900;
    modificationTime.tm_mon = 4;
    modificationTime.tm_mday = 20;
    modificationTime.tm_hour = 17;
    modificationTime.tm_min = 42;
    modificationTime.tm_sec = 22;

    time(&utimeBuffer.actime);
    utimeBuffer.modtime = mktime(&modificationTime);
    utime(path, &utimeBuffer);
}

TEST(ShouldParseTheLastModificationTimeToAShortValue)
{

    ZipReader* reader = new ZipReader("resources/TimeTest.zip");
    FileHeader* header = reader->extractFileHeaders().front();

    unsigned short expectedTimeValue = header->lastModifiedTime_;
    setLastModificationTime("resources/timetest.txt");
    unsigned short actualTimeValue = header->parseTimeToShort(getLastModificationTimeAndDate("resources/timetest.txt"));

    CHECK_CLOSE(expectedTimeValue, actualTimeValue, 1);

    delete reader;
    delete header;

}

TEST(ShouldParseTheLastModificationDateToAShortValue)
{
    ZipReader* reader = new ZipReader("resources/TimeTest.zip");
    FileHeader* header = reader->extractFileHeaders().front();

    unsigned short expectedDateValue = header->lastModifiedDate_;
    setLastModificationTime("resources/timetest.txt");
    unsigned short actualDateValue = header->parseDateToShort(getLastModificationTimeAndDate("resources/timetest.txt"));

    CHECK(expectedDateValue == actualDateValue);

    delete reader;
    delete header;
}

TEST(TestTheOutOperatorOfTheFileHeader)
{
    ZipReader* reader = new ZipReader("resources/TestOperator.zip");
    FileHeader* header = reader->extractFileHeaders().front();
    
    std::ostringstream out;
    out << *header;
    int expected = 100;
    CHECK_EQUAL(expected, out.tellp());
    delete reader;
    delete header;
}

TEST(TestTheOutOperatorOfTheCentralDirectory)
{
    ZipReader reader ("resources/TestOperator.zip");
    FileHeader* header = reader.extractFileHeaders().front();
    CentralDirectory centralDirectory (header);
    
    std::ostringstream out;
    out << centralDirectory;
    int expected = 92;
    CHECK_EQUAL(expected, out.tellp());

    delete header;
}

TEST(ShouldSetTheRigthValuesToAFileHeaderOfADirectory)
{
    FilePathData directoryPath;
    directoryPath.fullPath_ = "resources/TestDirectoryFileHeader";
    directoryPath.relativePath_ = "TestDirectoryFileHeader/";
    ZipBuilder builder;
    
    FileHeader* expectedHeader = builder.buildFileHeaderStructure(directoryPath);
    
    CHECK(expectedHeader->unCompressedSize_ ==0);
    CHECK(expectedHeader->fileData_ == 0);
    CHECK(expectedHeader->fileNameLength_ == directoryPath.relativePath_.size());
}